#pragma once

#include <string>
#include <iostream>
#include <map>

using namespace std;

#include "topdbs_connection.hpp"

namespace topdbs
{
	struct STConn
	{
		SQLConnection* m_pConnection;
		eConnSt_t m_status;
		virtual ~STConn()
		{
			if(m_pConnection)
			{
				delete m_pConnection;
				m_pConnection = nullptr;
			}
		}
	};

	/**
	 * @brief database connection pool single class defined
	 * Usage:
	 * InitEnv() -> GetConnection() -> ReleaseConnection()
	 * 
	 */
	class TOPDBS_API SQLConnectionPool
	{
	private:
		uint16_t m_minConn;
		uint16_t m_maxConn;
		eDBSClient_t m_dbsClient;
		string m_dbString;
		string m_user;
		string m_pass;
		string m_charset;
		bool m_encrypt;
		void* m_pOption;
		
		std::map<uint64_t,STConn*> m_StConns;
		uint16_t m_current_pool_size;
		uint16_t m_current_idle_size;

		static std::mutex  m_lock; 
		static SQLConnectionPool* m_instance;
		static bool m_status;
		class AutoRelease
		{
			public:
			~AutoRelease()
			{
				UnInitEnv();
			};
		};	    
		static AutoRelease m_release;   

		SQLConnectionPool(){};
		SQLConnectionPool(const SQLConnectionPool& a) = delete;
		SQLConnectionPool& operator=(const SQLConnectionPool& a) = delete;
		int NewConnection();	 

	public:		
		~SQLConnectionPool();	
		int NewConnectionPool(
			int minConn,int maxConn,
			eDBSClient_t dbsClient,
			const string& dbString,
			const string& user = string(),
			const string& pass = string(),
			const string& charset = string(),
			bool encrypt = false,
			void* pOption = NULL );
		int DeleteConnectionPool();
		SQLConnection* GetIdleConnection();
		int ReleaseIdleConnection(SQLConnection* pConnection);

		static SQLConnectionPool* getInstance();

		static int InitEnv(
			uint16_t minConn,
			uint16_t maxConn,
			eDBSClient_t dbsClient,
			const string& dbString,
			const string& user = string(),
			const string& pass = string(),
			const string& charset = string(),
			bool encrypt = false,
			void* pOption = NULL );

		static int InitEnv(
			eDBSClient_t dbsClient,
			const string& dbString,
			const string& user = string(),
			const string& pass = string(),
			const string& charset = string(),
			bool encrypt = false,
			void* pOption = NULL );      

		static int InitEnv( const string& dbsfile,const string& dbsgroup = string());  			 

		static int UnInitEnv();	 

		static SQLConnection* GetConnection();
		static int ReleaseConnection(SQLConnection* pConnection);     
	};
}